<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>Omit needless words</title>
  <style>
* {
  box-sizing: border-box;
}

body {
  font-family: Helvetica, Arial, sans-serif;
  max-width: 800px;
  margin: 0 auto;
  padding: 40px 20px;
  background: #f5f5f5;
  min-height: 100vh;
}

h1 {
  font-size: 28px;
  font-weight: 600;
  color: #333;
  margin-bottom: 8px;
}

.subtitle {
  color: #666;
  margin-bottom: 32px;
  font-size: 16px;
}

.input-section {
  margin-bottom: 24px;
}

label {
  display: block;
  font-weight: 500;
  margin-bottom: 8px;
  color: #333;
}

textarea {
  width: 100%;
  height: 180px;
  padding: 16px;
  font-size: 16px;
  font-family: Helvetica, Arial, sans-serif;
  border: 2px solid #ddd;
  border-radius: 8px;
  resize: vertical;
  transition: border-color 0.2s;
}

textarea:focus {
  outline: none;
  border-color: #007aff;
}

button {
  background: #007aff;
  color: white;
  border: none;
  padding: 14px 28px;
  font-size: 16px;
  font-weight: 500;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.2s;
}

button:hover {
  background: #0056b3;
}

button:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.result-section {
  margin-top: 32px;
  display: none;
}

.result-section.visible {
  display: block;
}

.result-box {
  background: white;
  padding: 24px;
  border-radius: 8px;
  border: 2px solid #ddd;
  line-height: 1.8;
  font-size: 18px;
  white-space: pre-wrap;
}

.result-box del {
  background: #ffebee;
  color: #c62828;
  text-decoration: line-through;
  padding: 2px 4px;
  border-radius: 3px;
}

.stats {
  margin-top: 16px;
  padding: 16px;
  background: #e8f5e9;
  border-radius: 8px;
  color: #2e7d32;
  font-size: 14px;
}

.stats.hidden {
  display: none;
}

.streaming-indicator {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #666;
  font-size: 14px;
  margin-bottom: 12px;
}

.streaming-indicator.hidden {
  display: none;
}

.pulse {
  width: 8px;
  height: 8px;
  background: #007aff;
  border-radius: 50%;
  animation: pulse 1s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

.error {
  background: #ffebee;
  color: #c62828;
  padding: 16px;
  border-radius: 8px;
  margin-top: 16px;
}

.debug-panel {
  margin-top: 32px;
  background: #1e1e1e;
  border-radius: 8px;
  color: #d4d4d4;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 12px;
}

.debug-panel summary {
  padding: 12px 16px;
  cursor: pointer;
  background: #2d2d2d;
  border-radius: 8px;
  color: #888;
  user-select: none;
}

.debug-panel[open] summary {
  border-radius: 8px 8px 0 0;
}

.debug-controls {
  display: flex;
  gap: 16px;
  align-items: center;
  padding: 8px 16px;
  background: #252525;
  border-bottom: 1px solid #333;
}

.debug-btn {
  background: #444;
  color: #ddd;
  border: none;
  padding: 6px 12px;
  font-size: 11px;
  border-radius: 4px;
  cursor: pointer;
}

.debug-btn:hover {
  background: #555;
}

.debug-controls label {
  color: #888;
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.debug-log {
  max-height: 300px;
  overflow-y: auto;
  padding: 12px 16px;
  border-bottom: 1px solid #333;
}

.debug-log .log-entry {
  padding: 2px 0;
  border-bottom: 1px solid #2a2a2a;
}

.debug-log .log-entry:last-child {
  border-bottom: none;
}

.debug-log .timestamp {
  color: #666;
  margin-right: 8px;
}

.debug-log .log-info {
  color: #6a9fb5;
}

.debug-log .log-success {
  color: #7c9a5e;
}

.debug-log .log-warning {
  color: #d4a656;
}

.debug-log .log-error {
  color: #c75050;
}

.debug-log .log-data {
  color: #9b59b6;
}

.debug-section {
  padding: 12px 16px;
  border-bottom: 1px solid #333;
}

.debug-section:last-child {
  border-bottom: none;
}

.debug-section strong {
  color: #888;
  display: block;
  margin-bottom: 8px;
}

.debug-raw {
  background: #252525;
  padding: 12px;
  border-radius: 4px;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 200px;
  overflow-y: auto;
  margin: 0;
}

#debug-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
}

.stat-item {
  background: #252525;
  padding: 8px 12px;
  border-radius: 4px;
}

.stat-item .stat-label {
  color: #666;
  font-size: 10px;
  text-transform: uppercase;
}

.stat-item .stat-value {
  color: #6a9fb5;
  font-size: 14px;
  font-weight: bold;
}

.options-row {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.option-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.option-group label {
  font-weight: 500;
  color: #333;
  font-size: 14px;
}

select {
  padding: 10px 14px;
  font-size: 16px;
  border: 2px solid #ddd;
  border-radius: 8px;
  background: white;
  cursor: pointer;
  transition: border-color 0.2s;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

select:focus {
  outline: none;
  border-color: #007aff;
}

.prompt-editor {
  margin-bottom: 24px;
  background: #fff;
  border: 2px solid #ddd;
  border-radius: 8px;
}

.prompt-editor summary {
  padding: 12px 16px;
  cursor: pointer;
  font-weight: 500;
  color: #333;
  user-select: none;
}

.prompt-editor summary:hover {
  background: #f9f9f9;
}

.prompt-editor[open] summary {
  border-bottom: 1px solid #ddd;
}

.prompt-editor-content {
  padding: 16px;
}

.prompt-textarea {
  width: 100%;
  height: 300px;
  padding: 12px;
  font-size: 16px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  border: 1px solid #ddd;
  border-radius: 6px;
  resize: vertical;
  line-height: 1.5;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.prompt-textarea:focus {
  outline: none;
  border-color: #007aff;
}

.prompt-buttons {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.prompt-btn {
  padding: 8px 16px;
  font-size: 13px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.2s;
}

.prompt-btn-secondary {
  background: #f5f5f5;
  color: #333;
  border: 1px solid #ddd;
}

.prompt-btn-secondary:hover {
  background: #e8e8e8;
}

.custom-prompt-banner {
  background: #fff3cd;
  border: 1px solid #ffc107;
  color: #856404;
  padding: 12px 16px;
  border-radius: 8px;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.custom-prompt-banner.hidden {
  display: none;
}

.custom-prompt-banner span {
  font-size: 14px;
}

.toggle-prompt-btn {
  background: #856404;
  color: white;
  border: none;
  padding: 6px 12px;
  font-size: 12px;
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
}

.toggle-prompt-btn:hover {
  background: #6d5303;
}
  </style>
</head>
<body>
  <h1>Omit needless words</h1>
  <p class="subtitle">Paste your text below and let Claude identify words that can be removed without changing the meaning.</p>
  
  <div class="input-section">
    <label for="input-text">Your text</label>
    <textarea id="input-text" placeholder="Paste your text here..."></textarea>
  </div>

  <div class="options-row">
    <div class="option-group">
      <label for="model-select">Model</label>
      <select id="model-select">
        <option value="claude-haiku-4-5-20251001">Claude Haiku 4.5</option>
        <option value="claude-sonnet-4-5-20250929">Claude Sonnet 4.5</option>
        <option value="claude-opus-4-5-20251101">Claude Opus 4.5</option>
      </select>
    </div>
  </div>

  <details class="prompt-editor" id="prompt-editor">
    <summary>System prompt</summary>
    <div class="prompt-editor-content">
      <textarea id="system-prompt" class="prompt-textarea"></textarea>
      <div class="prompt-buttons">
        <button type="button" class="prompt-btn prompt-btn-secondary" id="save-prompt-btn">Save as custom prompt</button>
        <button type="button" class="prompt-btn prompt-btn-secondary" id="reset-prompt-btn">Reset to default</button>
      </div>
    </div>
  </details>

  <div id="custom-prompt-banner" class="custom-prompt-banner hidden">
    <span id="prompt-banner-text">Running with a custom system prompt</span>
    <button type="button" class="toggle-prompt-btn" id="toggle-prompt-btn">Use default prompt</button>
  </div>

  <button id="analyze-btn">Analyze text</button>
  
  <div id="error" class="error" style="display: none;"></div>
  
  <div id="result-section" class="result-section">
    <div id="streaming-indicator" class="streaming-indicator hidden">
      <div class="pulse"></div>
      <span>Streaming response...</span>
    </div>
    <label>Result</label>
    <div id="result-box" class="result-box"></div>
    <div id="stats" class="stats hidden"></div>
  </div>

  <details id="debug-panel" class="debug-panel">
    <summary>Debug info</summary>
    <div class="debug-controls">
      <button type="button" id="clear-debug" class="debug-btn">Clear log</button>
      <label><input type="checkbox" id="auto-scroll" checked> Auto-scroll</label>
    </div>
    <div id="debug-log" class="debug-log"></div>
    <div class="debug-section">
      <strong>Raw accumulated text:</strong>
      <pre id="debug-raw-text" class="debug-raw"></pre>
    </div>
    <div class="debug-section">
      <strong>Last parsed event:</strong>
      <pre id="debug-last-event" class="debug-raw"></pre>
    </div>
    <div class="debug-section">
      <strong>Buffer state:</strong>
      <pre id="debug-buffer" class="debug-raw"></pre>
    </div>
    <div class="debug-section">
      <strong>Stream stats:</strong>
      <div id="debug-stats"></div>
    </div>
  </details>

<script type="module">
const inputText = document.getElementById('input-text');
const analyzeBtn = document.getElementById('analyze-btn');
const errorDiv = document.getElementById('error');
const resultSection = document.getElementById('result-section');
const resultBox = document.getElementById('result-box');
const stats = document.getElementById('stats');
const streamingIndicator = document.getElementById('streaming-indicator');
const modelSelect = document.getElementById('model-select');
const systemPromptTextarea = document.getElementById('system-prompt');
const savePromptBtn = document.getElementById('save-prompt-btn');
const resetPromptBtn = document.getElementById('reset-prompt-btn');
const customPromptBanner = document.getElementById('custom-prompt-banner');
const togglePromptBtn = document.getElementById('toggle-prompt-btn');
const promptBannerText = document.getElementById('prompt-banner-text');

// Default system prompt
const DEFAULT_PROMPT = `You are an editor applying Strunk & White's principle "Omit needless words."

Your task: Return the EXACT input text, but wrap words and phrases that could be omitted in <del></del> tags.

CRITICAL: Only mark words/phrases where the sentence remains grammatically correct AND means the same thing after removal. Never mark verbs, subjects, or words that carry meaning.

Good targets:
- Filler words: "very", "really", "just", "quite", "actually", "basically", "literally"
- Unnecessary "that" (only when grammatically optional)
- Wordy phrases where part can be cut: "in order to" (mark "in order"), "due to the fact that" (mark "the fact"), "at this point in time" (mark "point in")
- Redundant modifiers: "past history" (mark "past"), "future plans" (mark "future"), "end result" (mark "end")
- Filler phrases: "it is important to note that", "as a matter of fact"

NEVER mark:
- Verbs (like "using", "producing", "is", "are")
- Subjects or objects that carry meaning
- Words where removal changes the meaning or breaks grammar

Rules:
1. Preserve all newlines, punctuation, and spacing exactly
2. Return ONLY the marked-up text with no explanation

Input text:
\${text}

Output the text with <del></del> tags around omittable words and phrases:`;

// State for custom prompt
let useCustomPrompt = false;

// Check if there's a saved custom prompt
function hasCustomPrompt() {
  return !!localStorage.getItem('omit-needless-words-custom-prompt');
}

// Initialize prompt textarea and check for saved custom prompt
function initPromptEditor() {
  const savedCustomPrompt = localStorage.getItem('omit-needless-words-custom-prompt');
  const savedUseCustom = localStorage.getItem('omit-needless-words-use-custom') === 'true';

  if (savedCustomPrompt && savedUseCustom) {
    useCustomPrompt = true;
    systemPromptTextarea.value = savedCustomPrompt;
  } else {
    useCustomPrompt = false;
    systemPromptTextarea.value = DEFAULT_PROMPT;
  }
  updatePromptBanner();
}

function updatePromptBanner() {
  const savedCustomPrompt = localStorage.getItem('omit-needless-words-custom-prompt');

  if (savedCustomPrompt) {
    customPromptBanner.classList.remove('hidden');
    if (useCustomPrompt) {
      // Using custom prompt
      promptBannerText.textContent = 'Running with a custom system prompt';
      togglePromptBtn.textContent = 'Use default prompt';
    } else {
      // Using default but have a saved custom prompt available
      promptBannerText.textContent = 'Using default prompt (custom prompt saved)';
      togglePromptBtn.textContent = 'Use custom prompt';
    }
  } else {
    // No custom prompt saved
    customPromptBanner.classList.add('hidden');
  }

  // Update save button text
  updateSaveButtonText();
}

function updateSaveButtonText() {
  const savedCustomPrompt = localStorage.getItem('omit-needless-words-custom-prompt');
  if (savedCustomPrompt) {
    savePromptBtn.textContent = 'Update custom prompt';
  } else {
    savePromptBtn.textContent = 'Save as custom prompt';
  }
}

function getCurrentPrompt() {
  if (useCustomPrompt) {
    return localStorage.getItem('omit-needless-words-custom-prompt') || DEFAULT_PROMPT;
  }
  return DEFAULT_PROMPT;
}

savePromptBtn.addEventListener('click', () => {
  const promptText = systemPromptTextarea.value.trim();
  if (promptText) {
    // If saving the default prompt, clear the custom prompt instead
    if (promptText === DEFAULT_PROMPT.trim()) {
      localStorage.removeItem('omit-needless-words-custom-prompt');
      localStorage.setItem('omit-needless-words-use-custom', 'false');
      useCustomPrompt = false;
    } else {
      localStorage.setItem('omit-needless-words-custom-prompt', promptText);
      localStorage.setItem('omit-needless-words-use-custom', 'true');
      useCustomPrompt = true;
    }
    updatePromptBanner();
  }
});

resetPromptBtn.addEventListener('click', () => {
  systemPromptTextarea.value = DEFAULT_PROMPT;
});

togglePromptBtn.addEventListener('click', () => {
  const savedCustomPrompt = localStorage.getItem('omit-needless-words-custom-prompt');

  if (useCustomPrompt) {
    // Switch to default
    useCustomPrompt = false;
    localStorage.setItem('omit-needless-words-use-custom', 'false');
    systemPromptTextarea.value = DEFAULT_PROMPT;
  } else if (savedCustomPrompt) {
    // Switch to custom
    useCustomPrompt = true;
    localStorage.setItem('omit-needless-words-use-custom', 'true');
    systemPromptTextarea.value = savedCustomPrompt;
  }
  updatePromptBanner();
});

// Initialize on load
initPromptEditor();

// Get the API key from localStorage or prompt the user to enter it
function getApiKey() {
  let apiKey = localStorage.getItem("ANTHROPIC_API_KEY");
  if (!apiKey) {
    apiKey = prompt("Please enter your Anthropic API key:");
    if (apiKey) {
      localStorage.setItem("ANTHROPIC_API_KEY", apiKey);
    }
  }
  return apiKey;
}

// Debug elements
const debugLog = document.getElementById('debug-log');
const debugRawText = document.getElementById('debug-raw-text');
const debugLastEvent = document.getElementById('debug-last-event');
const debugBuffer = document.getElementById('debug-buffer');
const debugStats = document.getElementById('debug-stats');
const clearDebugBtn = document.getElementById('clear-debug');
const autoScrollCheckbox = document.getElementById('auto-scroll');

// Debug state
let streamStats = {
  chunksReceived: 0,
  bytesReceived: 0,
  eventsProcessed: 0,
  textDeltaEvents: 0,
  parseErrors: 0,
  totalTextLength: 0,
  startTime: null,
  lastChunkTime: null
};

function log(message, type = 'info') {
  const entry = document.createElement('div');
  entry.className = 'log-entry';
  const now = new Date();
  const timestamp = now.toLocaleTimeString() + '.' + String(now.getMilliseconds()).padStart(3, '0');
  entry.innerHTML = `<span class="timestamp">[${timestamp}]</span><span class="log-${type}">${escapeHtml(message)}</span>`;
  debugLog.appendChild(entry);
  
  if (autoScrollCheckbox.checked) {
    debugLog.scrollTop = debugLog.scrollHeight;
  }
}

function escapeHtml(text) {
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

function updateDebugStats() {
  const elapsed = streamStats.startTime ? ((streamStats.lastChunkTime || Date.now()) - streamStats.startTime) / 1000 : 0;
  const rate = elapsed > 0 ? (streamStats.bytesReceived / elapsed).toFixed(0) : 0;
  
  debugStats.innerHTML = `
    <div class="stat-item"><div class="stat-label">Chunks</div><div class="stat-value">${streamStats.chunksReceived}</div></div>
    <div class="stat-item"><div class="stat-label">Bytes</div><div class="stat-value">${streamStats.bytesReceived}</div></div>
    <div class="stat-item"><div class="stat-label">Events</div><div class="stat-value">${streamStats.eventsProcessed}</div></div>
    <div class="stat-item"><div class="stat-label">Text Deltas</div><div class="stat-value">${streamStats.textDeltaEvents}</div></div>
    <div class="stat-item"><div class="stat-label">Parse Errors</div><div class="stat-value">${streamStats.parseErrors}</div></div>
    <div class="stat-item"><div class="stat-label">Text Length</div><div class="stat-value">${streamStats.totalTextLength}</div></div>
    <div class="stat-item"><div class="stat-label">Elapsed</div><div class="stat-value">${elapsed.toFixed(1)}s</div></div>
    <div class="stat-item"><div class="stat-label">Rate</div><div class="stat-value">${rate} B/s</div></div>
  `;
}

function resetDebugStats() {
  streamStats = {
    chunksReceived: 0,
    bytesReceived: 0,
    eventsProcessed: 0,
    textDeltaEvents: 0,
    parseErrors: 0,
    totalTextLength: 0,
    startTime: null,
    lastChunkTime: null
  };
  updateDebugStats();
}

clearDebugBtn.addEventListener('click', () => {
  debugLog.innerHTML = '';
  debugRawText.textContent = '';
  debugLastEvent.textContent = '';
  debugBuffer.textContent = '';
  resetDebugStats();
});

analyzeBtn.addEventListener('click', async () => {
  const text = inputText.value.trim();

  if (!text) {
    showError('Please enter some text to analyze.');
    return;
  }

  const apiKey = getApiKey();
  if (!apiKey) {
    showError('API key not found. Please enter your Anthropic API key.');
    return;
  }

  // Clear previous state
  debugLog.innerHTML = '';
  resetDebugStats();
  
  log('Starting analysis...', 'info');
  log(`Input text length: ${text.length} chars, ~${text.split(/\s+/).length} words`, 'info');
  
  analyzeBtn.disabled = true;
  errorDiv.style.display = 'none';
  resultBox.innerHTML = '';
  stats.classList.add('hidden');
  resultSection.classList.add('visible');
  streamingIndicator.classList.remove('hidden');
  
  try {
    await analyzeTextStream(text, apiKey);
    updateStats(text);
    log('Stream completed successfully', 'success');
  } catch (err) {
    log(`ERROR: ${err.message}`, 'error');
    log(`Stack: ${err.stack}`, 'error');
    showError('Error analyzing text: ' + err.message);
  } finally {
    analyzeBtn.disabled = false;
    streamingIndicator.classList.add('hidden');
    updateDebugStats();
  }
});

async function analyzeTextStream(text, apiKey) {
  // Get the current prompt template and substitute the text
  const promptTemplate = getCurrentPrompt();
  const prompt = promptTemplate.replace('${text}', text);

  // Get the selected model
  const selectedModel = modelSelect.value;

  log(`Using model: ${selectedModel}`, 'info');
  log(`Using ${useCustomPrompt ? 'custom' : 'default'} prompt`, 'info');
  log('Sending API request...', 'info');
  streamStats.startTime = Date.now();

  const response = await fetch("https://api.anthropic.com/v1/messages", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": apiKey,
      "anthropic-version": "2023-06-01",
      "anthropic-dangerous-direct-browser-access": "true"
    },
    body: JSON.stringify({
      model: selectedModel,
      max_tokens: 4000,
      stream: true,
      messages: [
        { role: "user", content: prompt }
      ]
    })
  });

  log(`Response status: ${response.status} ${response.statusText}`, response.ok ? 'success' : 'error');

  if (!response.ok) {
    const errorText = await response.text();
    log(`Error response body: ${errorText}`, 'error');
    throw new Error(`API request failed: ${response.status} - ${errorText}`);
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let fullText = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    streamStats.chunksReceived++;
    streamStats.lastChunkTime = Date.now();
    const chunk = decoder.decode(value, { stream: true });
    streamStats.bytesReceived += chunk.length;
    buffer += chunk;
    debugBuffer.textContent = buffer.slice(-500);

    const lines = buffer.split('\n');
    buffer = lines.pop() || '';

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = line.slice(6);
        if (data === '[DONE]') continue;

        try {
          const event = JSON.parse(data);
          streamStats.eventsProcessed++;
          debugLastEvent.textContent = JSON.stringify(event, null, 2);

          if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') {
            streamStats.textDeltaEvents++;
            const text = event.delta.text;
            fullText += text;
            streamStats.totalTextLength = fullText.length;
            debugRawText.textContent = fullText;
            renderText(fullText);
            log(`Text delta: +${text.length} chars`, 'data');
          }
        } catch (e) {
          streamStats.parseErrors++;
          log(`Parse error: ${e.message}`, 'warning');
        }
      }
    }
    updateDebugStats();
  }

  log(`Stream complete: ${fullText.length} chars total`, 'success');
}

function renderText(text) {
  // Sanitize text but preserve del tags and newlines
  const sanitized = text
    .replace(/<(?!\/?del\b)[^>]*>/g, '') // Remove all tags except <del> and </del>
    .replace(/\n/g, '<br>'); // Convert newlines to <br>
  
  resultBox.innerHTML = sanitized;
}

function updateStats(originalText) {
  const delElements = resultBox.querySelectorAll('del');
  const omittedWords = delElements.length;
  const originalWordCount = originalText.split(/\s+/).filter(w => w.length > 0).length;
  const percentage = originalWordCount > 0 ? ((omittedWords / originalWordCount) * 100).toFixed(1) : 0;
  
  stats.innerHTML = `<strong>${omittedWords}</strong> word${omittedWords !== 1 ? 's' : ''} marked for omission out of <strong>${originalWordCount}</strong> total words (${percentage}% reduction)`;
  stats.classList.remove('hidden');
  
  log(`Final stats: ${omittedWords} words marked for omission out of ${originalWordCount} total`, 'success');
}

function showError(message) {
  errorDiv.textContent = message;
  errorDiv.style.display = 'block';
  resultSection.classList.remove('visible');
}
</script>
</body>
</html>
